﻿using System;
using System.Management.Automation;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.PowerShell;

namespace MS.InformationManagement.DocumentIDServiceApp.Registration
{
    [Cmdlet(VerbsCommon.New, "DocumentIDServiceApplicationProxy", SupportsShouldProcess = true)]
    internal sealed class NewDocumentIDServiceApplicationProxy : SPCmdlet
    {
        private const string UriParameterSetName = "Uri";
        private const string ServiceApplicationParameterSetName = "ServiceApplication";

        [Parameter(Mandatory = true)]
        [ValidateNotNullOrEmpty]
        public string Name { get; set; }

        [Parameter(Mandatory = true, ParameterSetName = UriParameterSetName)]
        [ValidateNotNullOrEmpty]
        public string Uri { get; set; }

        [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = ServiceApplicationParameterSetName)]
        public SPServiceApplicationPipeBind ServiceApplication { get; set; }

        protected override bool RequireUserFarmAdmin()
        {
            return true;
        }

        protected override void InternalProcessRecord()
        {
            // Ensure that the farm level required objects exist
            SPFarm farm = SPFarm.Local;
            if (null == farm)
            {
                ThrowTerminatingError(new InvalidOperationException("SharePoint server farm not found."),
                    ErrorCategory.ResourceUnavailable, this);
            }

            // Ensure that the sample web service exists
            DocumentIDServiceProxy serviceProxy = farm.ServiceProxies.GetValue<DocumentIDServiceProxy>();
            if (null == serviceProxy)
            {
                ThrowTerminatingError(new InvalidOperationException("DocumentID web service proxy not found."),
                    ErrorCategory.ResourceUnavailable, this);
            }

            // Check for an existing sample web service application proxy
            DocumentIDServiceApplicationProxy existingServiceApplicationProxy = serviceProxy.ApplicationProxies.GetValue<DocumentIDServiceApplicationProxy>();
            if (null != existingServiceApplicationProxy)
            {
                WriteError(new InvalidOperationException("DocumentID web service application proxy exists."),
                    ErrorCategory.ResourceExists, existingServiceApplicationProxy);

                // Skip the current record
                SkipProcessCurrentRecord();
            }

            // Get the service application Uri from the chosen parameter set
            Uri serviceApplicationUri = null;
            if (this.ParameterSetName == UriParameterSetName)
            {
                // The service application uri was explicitly provided
                serviceApplicationUri = new Uri(this.Uri);
            }
            else if (this.ParameterSetName == ServiceApplicationParameterSetName)
            {
                // Get a reference to the specified service application
                SPServiceApplication serviceApplication = this.ServiceApplication.Read();
                if (null == serviceApplication)
                {
                    WriteError(new InvalidOperationException("Service application not found."),
                        ErrorCategory.ResourceExists, serviceApplication);

                    // Skip the current record
                    SkipProcessCurrentRecord();
                }

                ISharedServiceApplication sharedServiceApplication = serviceApplication as ISharedServiceApplication;
                if (null == sharedServiceApplication)
                {
                    WriteError(new InvalidOperationException("Connecting to the specified service application is not supported."),
                        ErrorCategory.ResourceExists, serviceApplication);

                    // Skip the current record
                    SkipProcessCurrentRecord();
                }

                // Get the service application uri
                serviceApplicationUri = sharedServiceApplication.Uri;
            }
            else
            {
                // An unexpected parameter set was chosen
                ThrowTerminatingError(new InvalidOperationException("Invalid parameter set."),
                    ErrorCategory.InvalidArgument, this);
            }

            // Start processing using validated parameters
            if ((null != serviceApplicationUri) && (ShouldProcess(this.Name)))
            {
                // Create the sample service application proxy
                DocumentIDServiceApplicationProxy serviceApplicationProxy = new DocumentIDServiceApplicationProxy(
                    this.Name, serviceProxy, serviceApplicationUri);

                // Provision the sample service application proxy
                serviceApplicationProxy.Update(true);
                serviceApplicationProxy.Provision();
                serviceApplicationProxy.AddToDefaultGroup();

                // Write the new sample service application proxy to the pipeline
                WriteObject(serviceApplicationProxy);
            }
        }
    }
}
